package com.hulk.dryad.manage.s3.template;


import com.google.common.collect.Lists;
import com.hulk.dryad.manage.s3.S3FsProperties;
import software.amazon.awssdk.core.ResponseInputStream;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3AsyncClient;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;
import software.amazon.awssdk.services.sts.StsAsyncClient;
import software.amazon.awssdk.services.sts.StsClient;
import software.amazon.awssdk.services.sts.model.Credentials;
import software.amazon.awssdk.services.sts.model.GetFederationTokenRequest;

import java.io.InputStream;
import java.util.List;
import java.util.function.Consumer;

/**
 *  文件系统
 *
 * @author hulk
 */
public interface FsTemplate {

	/**
	 * getStsClient
	 *
	 * @return StsClient
	 */
	StsClient getStsClient();

	/**
	 * getS3Client
	 *
	 * @return S3Client
	 */
	S3Client getS3Client();

	/**
	 * getStsAsyncClient
	 *
	 * @return StsAsyncClient
	 */
	StsAsyncClient getStsAsyncClient();

	/**
	 * getS3AsyncClient
	 *
	 * @return S3AsyncClient
	 */
	S3AsyncClient getS3AsyncClient();

	/**
	 * getFsProperties
	 *
	 * @returnFsProperties
	 */
	S3FsProperties getFsProperties();

	/**
	 * getFederationToken
	 *
	 * @return Credentials
	 */
	default Credentials getFederationToken() {
		return getFederationToken(-1);
	}

	/**
	 * getFederationToken
	 *
	 * @param timeOut time out seconds
	 * @return Credentials
	 */
	Credentials getFederationToken(int timeOut);

	/**
	 * getFederationToken
	 *
	 * @param bucket  bucket
	 * @param timeOut time out seconds
	 * @return Credentials
	 */
	Credentials getFederationToken(String bucket, int timeOut);

	/**
	 * getFederationToken
	 *
	 * @param federationTokenRequest GetFederationTokenRequest
	 * @return Credentials
	 */
	Credentials getFederationToken(GetFederationTokenRequest federationTokenRequest);

	/**
	 * getSessionToken
	 *
	 * @return Credentials
	 */
	Credentials getSessionToken();

	/**
	 * headBucket
	 *
	 * @param bucket bucket
	 * @return HeadBucketResponse
	 */
	HeadBucketResponse headBucket(String bucket);

	/**
	 * 创建 存储桶
	 *
	 * @param createBucketRequest 存储桶名称
	 * @return 是否成功
	 */
	boolean createBucket(Consumer<CreateBucketRequest.Builder> createBucketRequest);

	/**
	 * 删除 存储桶
	 *
	 * @param bucketName 存储桶名称
	 * @return 是否成功
	 */
	boolean deleteBucket(String bucketName);

	/**
	 * 判断桶是否存在
	 *
	 * @return 是否存在
	 */
	boolean isBucketExist();

	/**
	 * 判断桶是否存在
	 *
	 * @param bucket bucket
	 * @return 是否存在
	 */
	boolean isBucketExist(String bucket);

	/**
	 * head
	 *
	 * @param headObjectRequest headObjectRequest
	 * @return HeadObjectResponse
	 */
	HeadObjectResponse head(Consumer<HeadObjectRequest.Builder> headObjectRequest);

	/**
	 * get
	 *
	 * @param getObjectRequest GetObjectRequest
	 * @return ResponseInputStream
	 */
	ResponseInputStream<GetObjectResponse> get(GetObjectRequest getObjectRequest);

	/**
	 * copy 文件
	 *
	 * @param copyObjectRequest
	 */
	void copy(Consumer<CopyObjectRequest.Builder> copyObjectRequest);

	/**
	 * list
	 *
	 * @return file list
	 */
	default List<String> list() {
		return list(null);
	}

	/**
	 * list
	 *
	 * @param prefix Object key prefix
	 * @return file list
	 */
	default List<String> list(String prefix) {
		return list(prefix, 100);
	}

	/**
	 * list
	 *
	 * @param prefix Object key prefix
	 * @param size   page size
	 * @return file list
	 */
	default List<String> list(String prefix, int size) {
		return list(prefix, size, null);
	}

	/**
	 * list
	 *
	 * @param prefix  Object key prefix
	 * @param size    page size
	 * @param lastKey start after this Object
	 * @return file list
	 */
	List<String> list(String prefix, int size, String lastKey);

	/**
	 * list
	 *
	 * @param bucket  bucket
	 * @param prefix  Object key prefix
	 * @param size    page size
	 * @param lastKey start after this Object
	 * @return file list
	 */
	List<String> list(String bucket, String prefix, int size, String lastKey);

	/**
	 * 文件上传
	 *
	 * @param key           file key
	 * @param in            InputStream
	 * @param contentLength contentLength
	 * @return PutObjectResponse
	 */
	PutObjectResponse upload(String key, InputStream in, long contentLength);

	/**
	 * 文件上传
	 *
	 * @param bucket        bucket
	 * @param key           file key
	 * @param in            InputStream
	 * @param contentLength contentLength
	 * @return PutObjectResponse
	 */
	PutObjectResponse upload(String bucket, String key, InputStream in, long contentLength);

	/**
	 * 创建分片上传
	 *
	 * @param currentObject 当前的文件
	 * @return uploadId
	 */
	String createMultipartUpload(String currentObject);

	/**
	 * 创建分片上传
	 *
	 * @param bucket        bucket
	 * @param currentObject 当前的文件
	 * @return uploadId
	 */
	String createMultipartUpload(String bucket, String currentObject);

	/**
	 * 分片上传
	 *
	 * @param uploadPartRequest 上传请求
	 * @param requestBody       请求实体
	 * @return 响应
	 */
	UploadPartResponse uploadPart(UploadPartRequest uploadPartRequest, RequestBody requestBody);

	/**
	 * 结束分片上传
	 *
	 * @param currentObject 当前的文件
	 * @param uploadId      uploadId
	 * @param eTagList      eTagList
	 * @return 响应
	 */
	CompleteMultipartUploadResponse completeMultipartUpload(String currentObject, String uploadId, List<CompletedPart> eTagList);

	/**
	 * 结束分片上传
	 *
	 * @param bucket        bucket
	 * @param currentObject 当前的文件
	 * @param uploadId      uploadId
	 * @param eTagList      eTagList
	 * @return 响应
	 */
	CompleteMultipartUploadResponse completeMultipartUpload(String bucket, String currentObject, String uploadId, List<CompletedPart> eTagList);

	/**
	 * 删除文件
	 *
	 * @param keys 对象 key 列表
	 * @return deleted list
	 */
	default List<DeletedObject> delete(String... keys) {
		return delete(Lists.newArrayList(keys));
	}

	/**
	 * 删除文件
	 *
	 * @param keys 对象 key 列表
	 * @return deleted list
	 */
	List<DeletedObject> delete(List<String> keys);

	/**
	 * 删除文件
	 *
	 * @param bucket bucket
	 * @param keys   对象 key 列表
	 * @return deleted list
	 */
	List<DeletedObject> delete(String bucket, List<String> keys);

}
